﻿using log4net;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using RabbitMQ.Client.Exceptions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsumerMQ.Models
{
    /// <summary>
    /// 監聽基類 (正常消费者)
    /// 創建子類，繼承它，并實現Process方法（處理消息的方法）
    /// </summary>
    public class RabbitListener : BackgroundService
    {
        private readonly IConnection connection;
        private readonly IModel channel;
        private readonly string ExchangeName;
        private readonly string QueueName;
        private ILog log;

        public RabbitListener(IOptions<RabbitMQSetting> options)
        {
            try
            {
                //创建连接工厂对象
                var factory = new ConnectionFactory()
                {
                    // 这是我这边的配置,自己改成自己用就好
                    HostName = options.Value.RabbitHost,
                    UserName = options.Value.RabbitUserName,
                    Password = options.Value.RabbitPassword,
                    Port = options.Value.RabbitPort,
                };
                this.connection = factory.CreateConnection();
                this.channel = connection.CreateModel();

                this.ExchangeName = "ExchangeName_GLZ";
                this.QueueName = "QueueName_GLZ";

                this.log = LogManager.GetLogger(Startup.repository.Name, typeof(RabbitListener));
                log.Info("init RabbitListener");
            }
            catch (Exception ex)
            {
                log.Error($"RabbitListener init error,ex:{ex.Message}");
            }
        }

        protected override Task ExecuteAsync(CancellationToken stoppingToken)
        {
            throw new NotImplementedException();
        }

        public override Task StopAsync(CancellationToken cancellationToken)
        {
            this.connection.Close();
            return Task.CompletedTask;
        }

        public override Task StartAsync(CancellationToken cancellationToken)
        {
            Register();
            return Task.CompletedTask;
        }

        protected string RouteKey;

        // 处理消息的方法
        public virtual bool Process(string message)
        {
            throw new NotImplementedException();
        }

        // 注册消费者监听在这里
        public void Register()
        {
            log.Info($"RabbitListener register,routeKey:{RouteKey}");

            channel.BasicQos(0, 1, false);  //设置预取消息，避免公平轮训问题，可以根据需要设置预取消息数，这里是1

            channel.ExchangeDeclare(exchange: ExchangeName, type: "topic");

            //声明一个队列
            channel.QueueDeclare(queue: QueueName,//消息队列名称
                  durable: true,//是否缓存
                exclusive: false,
               autoDelete: false,
                arguments: null);

            channel.QueueBind(queue: QueueName, //消息队列名称
                              exchange: ExchangeName,
                              routingKey: RouteKey);


            //创建消费者对象
            var consumer = new EventingBasicConsumer(channel);
            consumer.Received += (model, ea) =>
            {
                try
                {
                    var body = ea.Body; //接收到的消息
                    var message = Encoding.UTF8.GetString(body.ToArray());
                    var result = Process(message);

                    if (result)
                    {
                        channel.BasicAck(ea.DeliveryTag, false);
                    }

                }
                catch (AlreadyClosedException ex)
                {
                    log.Error($"RabbitMQ is closed！error:{ex}");
                }
            };
            //消费者开启监听
            channel.BasicConsume(queue: QueueName, false, consumer: consumer);
        }

        public override void Dispose()
        {
            this.connection.Close();
            base.Dispose();
        }

    }
}
